#include "Cello.h"

struct Point {
  float x, y;
};
var Point = Cello(Point);

void example1() {
  var i0 = $(Int, 5);
  var i1 = $(Int, 3);
  var i2 = $(Int, 4);
  var items = new(Array, Int, i0, i1, i2);
  foreach (item in items) {
    print("the value %$ is of type %s\n", item, type_of(item));
  }
  print("Array of Integers: %$\n", items);  
  var prices = new(Table, String, Int);
  set(prices, $S("xxxxxxx"), $I(2333));
  foreach (key in prices) {
    var v = get(prices, key);
    print("price of %$ is %$\n", key, v);
  }
  foreach(i in range($I(len(items)))) {
    print("item range %$ is %$\n", i, get(items, i));
  }
  foreach(item in slice(items, _, _, $I(2))) {
    print("slice %$\n", item);
  }
  var p0 = $(Point, 0.0, 2.0);
  var p1 = new(Point, $(Point, 0.0, 2.0));
  print("p0: %$\np1:%$cmp: %i\nhash:%ul\n", p0, p1, $I(cmp(p0, p1)), $I(hash(p0)));
}

void example2() {
}

void example3() {
  var convert_to_int(var x) {
    var y = new(Int);
    look_from(y, x, 0);
    return y;
  }
  var x = tuple($S("1"), $S("2"), $S("3"));
  foreach(y in map(x, $(Function, convert_to_int))) {
    println("num: %$", y);
  }
}

var get_args(int argc, char** argv) {
  var args = new(Array, String);
  for (int i = 0; i < argc; i++) {
    push(args, new(String, $S(argv[i])));
  }
  return args;
}

var shift(var xs) {
  var x = copy(get(xs, $I(0)));
  pop_at(xs, $I(0));
  return x;
}


var read_entire_file(var file_path) {
  var content = new(String);
  with(f in new(File, file_path, $S("rb"))) {
    sseek(f, 0, SEEK_END);
    int64_t size = stell(f);
    resize(content, size);
    sseek(f, 0, SEEK_SET);
    sread(f, c_str(content), size);
  }
  return content;
}

int main(int argc, char** argv) {
// %() allocate value on stack 
// new allocate value on heap
  var args = get_args(argc, argv);
  var program_name = shift(args);
  if (len(args) <= 0) {
    println("Usage: %$ <input>", program_name);
    println("ERROR: No input is provided");
    return 1;
  }
  var file_path = shift(args);
  var content = read_entire_file(file_path);
  println("%s", content);
  return 0;
}
